package fleetctl

import (
	"context"
	"errors"
	"fmt"
	"os"

	"github.com/fleetdm/fleet/v4/server/vulnerabilities/macoffice"
	"github.com/fleetdm/fleet/v4/server/vulnerabilities/msrc"
	"github.com/fleetdm/fleet/v4/server/vulnerabilities/nvd"
	"github.com/fleetdm/fleet/v4/server/vulnerabilities/oval"
	klog "github.com/go-kit/log"
	"github.com/urfave/cli/v2"
)

func vulnerabilityDataStreamCommand() *cli.Command {
	var dir string
	return &cli.Command{
		Name:  "vulnerability-data-stream",
		Usage: "Download the vulnerability data stream",
		UsageText: `
fleetctl vulnerability-data-stream [options]

Downloads (if needed) the data streams that can be used by the Fleet server to process software for vulnerabilities.
`,
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:        "dir",
				EnvVars:     []string{"DIR"},
				Value:       "",
				Destination: &dir,
				Usage:       "Directory to place the data streams in",
			},
			configFlag(),
			contextFlag(),
			debugFlag(),
		},
		Action: func(c *cli.Context) error {
			if dir == "" {
				return errors.New("No directory provided")
			}
			err := os.MkdirAll(dir, 0o700)
			if err != nil {
				return err
			}

			log(c, "[-] Downloading CPE database...")
			err = nvd.DownloadCPEDBFromGithub(dir, "")
			if err != nil {
				return fmt.Errorf("Error downloading CPE database: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading CPE translations...")
			err = nvd.DownloadCPETranslationsFromGithub(dir, "")
			if err != nil {
				return fmt.Errorf("Error downloading CPE translations: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading NVD CVE feed...")
			err = nvd.DownloadCVEFeed(dir, "", false, klog.NewNopLogger())
			if err != nil {
				return fmt.Errorf("Error downloading NVD CVE feed: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading EPSS feed...")
			err = nvd.DownloadEPSSFeed(dir)
			if err != nil {
				return fmt.Errorf("Error downloading EPSS feed: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading CISA known exploits feed...")
			err = nvd.DownloadCISAKnownExploitsFeed(dir, "")
			if err != nil {
				return fmt.Errorf("Error downloading CISA known exploits feed: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading Oval definitions...")
			err = oval.Sync(dir, nil)
			if err != nil {
				return fmt.Errorf("Error downloading Oval definitions: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading MSRC artifacts...")
			ctx := context.Background()
			err = msrc.SyncFromGithub(ctx, dir, nil)
			if err != nil {
				return fmt.Errorf("Error downloading MSRC artifacts: %v", err)
			}
			log(c, " Done\n")

			log(c, "[-] Downloading MacOffice release notes...")
			err = macoffice.SyncFromGithub(ctx, dir)
			if err != nil {
				return fmt.Errorf("Error downloading MacOffice release notes: %v", err)
			}
			log(c, " Done\n")

			log(c, "[+] Data streams successfully downloaded!\n")
			return nil
		},
	}
}
